#ifndef THREADS_H_
#define THREADS_H_

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

using namespace std;

/*!
 *
 * \class Threads
 * \brief Permet d'instancier des threads.
 *
 */
class Threads
{
	private:
		pthread_t threadEcouteNouveauServeurPartie; /*!< Thread d'ecoute de nouveaux serveur de partie */
		pthread_t threadTraiteNouveauServeurPartie; /*!< Thread traitant les nouveaux serveurs de partie */

		pthread_t threadEcouteNouveauClient; /*!< Thread d'ecoute de nouveaux clients */
		pthread_t threadTraiteNouveauClient; /*!< Thread traitant les nouveaux clients */

		pthread_t threadLectureServeurPartie; /*!< Thread de lecture des serveurs de partie */
		pthread_t threadTraiteServeurPartie; /*!< Thread de traitement des messages des serveurs de partie */

		pthread_t threadTestServeurPartie; /*!< Thread testant la présence des serveurs de partie */

		pthread_t threadJeton; /*!< Thread envoyant le nouveau jeton aux serveurs de partie */




	public:
		Threads() {}

		/*!
		 *
		 * Initialisation du Thread d'Ecoute de nouveau serveur de partie
		 *
		 */
		pthread_t * initAttendServeurPartie()
		{	
			/* Initialise les attributs du threads */
			pthread_attr_t attr;
			pthread_attr_init(&attr);
			pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

			if( ! (pthread_create(&(this->threadEcouteNouveauServeurPartie), &attr, Threads::demarrerEcouteServeurPartie, static_cast<void *>(this))) )
			{
				printf("Creation du thread d'ecoute des serveurs de parties arrivants\n");
				return &(this->threadEcouteNouveauServeurPartie);
			}
			else
			{
				printf("Echec de la creation du thread d'ecoute des serveurs de parties arrivants\n");
				exit(0);
			}
		}
		static void * demarrerEcouteServeurPartie(void * thread)
		{
			static_cast<Threads *>(thread)->traitementEcouteServeurPartie();
			pthread_exit(NULL);
		}

		virtual void traitementEcouteServeurPartie() = 0;		
		/*!
		 *
		 * Initialisation du Thread de traitement des nouveaux serveurs de partie.
		 *
		 */
		pthread_t * initNouveauServeurPartie()
		{
			/* Initialise les attributs du threads */
			pthread_attr_t attr;
			pthread_attr_init(&attr);
			pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

			if( ! (pthread_create(&(this->threadTraiteNouveauServeurPartie), &attr, Threads::demarrerServeurPartie, static_cast<void *>(this))) )
			{
				printf("Creation du thread temporaire de traitement des nouveaux serveurs de partie\n");
				return &(this->threadTraiteNouveauServeurPartie);
			}
			else
			{
				printf("Echec de la creation du thread temporaire de traitement des nouveaux serveurs de partie\n");
				exit(0);
			}
		}
		static void * demarrerServeurPartie(void * thread)
		{
			static_cast<Threads *>(thread)->traitementNouveauServeurPartie();
			pthread_exit(NULL);
		}
		virtual void traitementNouveauServeurPartie() = 0;







	
		/*!
		 *
		 * Initialisation du Thread d'écoute de nouveaux clients.
		 *
		 */
		pthread_t * initAttendClient()
		{	
			/* Initialise les attributs du threads */
			pthread_attr_t attr;
			pthread_attr_init(&attr);
			pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

			if( ! (pthread_create(&(this->threadEcouteNouveauClient), &attr, Threads::demarrerEcouteClient, static_cast<void *>(this))) )
			{
				printf("Creation du thread d'ecoute de nouveaux clients\n");
				return &(this->threadEcouteNouveauClient);
			}
			else
			{
				printf("Echec de la creation du thread d'ecoute de nouveaux clients\n");
				exit(0);
			}
		}
		static void * demarrerEcouteClient(void * thread)
		{
			static_cast<Threads *>(thread)->traitementEcouteClient();
			pthread_exit(NULL);
		}

		virtual void traitementEcouteClient() = 0;
		/*!
		 *
		 * Initialisation du Thread de traitement de nouveaux clients.
		 *
		 */		
		pthread_t * initNouveauClient()
		{	
			/* Initialise les attributs du threads */
			pthread_attr_t attr;
			pthread_attr_init(&attr);
			pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

			if( ! (pthread_create(&(this->threadTraiteNouveauClient), &attr, Threads::demarrerClient, static_cast<void *>(this))) )
			{
				printf("Creation du thread temporaire de traitement de nouveaux clients\n");
				return &(this->threadTraiteNouveauClient);
			}
			else
			{
				printf("Echec de la creation temporaire de traitement de nouveaux clients\n");
				exit(0);
			}
		}
		static void * demarrerClient(void * thread)
		{
			static_cast<Threads *>(thread)->traitementClient();
			pthread_exit(NULL);
		}
		virtual void traitementClient() = 0;

		
		




		
		/*!
		 *
		 * Initialisation du Thread  de lecture des serveurs de partie.
		 *
		 */
		pthread_t * initLectureServeurPartie()
		{	
			/* Initialise les attributs du threads */
			pthread_attr_t attr;
			pthread_attr_init(&attr);
			pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

			if( ! (pthread_create(&(this->threadLectureServeurPartie), &attr, Threads::demarrerLectureServeurPartie, static_cast<void *>(this))) )
			{
				printf("Creation du thread de lecture des serveurs de partie\n");
				return &(this->threadLectureServeurPartie);
			}
			else
			{
				printf("Echec de la creation du thread de lecture des serveurs de partie\n");
				exit(0);
			}
		}
		static void * demarrerLectureServeurPartie(void * thread)
		{
			static_cast<Threads *>(thread)->traitementLectureServeurPartie();
			pthread_exit(NULL);
		}
		virtual void traitementLectureServeurPartie() = 0;
		/*!
		 *
		 * Initialisation du Thread de traitement des mesages des serveurs de partie.
		 *
		 */		
		pthread_t * initTraiteServeurPartie()
		{	
			/* Initialise les attributs du threads */
			pthread_attr_t attr;
			pthread_attr_init(&attr);
			pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

			if( ! (pthread_create(&(this->threadTraiteServeurPartie), &attr, Threads::demarrerTraiteServeurPartie, static_cast<void *>(this))) )
			{
				printf("Creation du thread de traitement des mesages des serveurs de partie\n");
				return &(this->threadTraiteServeurPartie);
			}
			else
			{
				printf("Echec de la creation de traitement des mesages des serveurs de partie\n");
				exit(0);
			}
		}
		static void * demarrerTraiteServeurPartie(void * thread)
		{
			static_cast<Threads *>(thread)->traitementServeurPartie();
			pthread_exit(NULL);
		}
		virtual void traitementServeurPartie() = 0;
		
		
		
		
		
		
		
		/*!
		 *
		 * Initialisation du Thread de test de présence des serveurs de partie.
		 *
		 */		
		pthread_t * initTestServeurPartie()
		{	
			/* Initialise les attributs du threads */
			pthread_attr_t attr;
			pthread_attr_init(&attr);
			pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

			if( ! (pthread_create(&(this->threadTestServeurPartie), &attr, Threads::demarrerTestServeurPartie, static_cast<void *>(this))) )
			{
				printf("Creation du thread de test de presence des serveurs de partie.\n");
				return &(this->threadTestServeurPartie);
			}
			else
			{
				printf("Echec de la creation du thread de test de presence des serveurs de partie.\n");
				exit(0);
			}
		}
		static void * demarrerTestServeurPartie(void * thread)
		{
			static_cast<Threads *>(thread)->traitementTestServeurPartie();
			pthread_exit(NULL);
		}
		virtual void traitementTestServeurPartie() = 0;








		/*!
		 *
		 * Initialisation du Thread d'envoie du jeton aux serveurs de partie.
		 *
		 */		
		pthread_t * initJeton()
		{	
			/* Initialise les attributs du threads */
			pthread_attr_t attr;
			pthread_attr_init(&attr);
			pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

			if( ! (pthread_create(&(this->threadJeton), &attr, Threads::demarrerJeton, static_cast<void *>(this))) )
			{
				printf("Creation du thread d'envoie du jeton aux serveurs de partie.\n");
				return &(this->threadJeton);
			}
			else
			{
				printf("Echec de la creation du thread d'envoie du jeton aux serveurs de partie.\n");
				exit(0);
			}
		}
		static void * demarrerJeton(void * thread)
		{
			static_cast<Threads *>(thread)->traitementJeton();
			pthread_exit(NULL);
		}
		virtual void traitementJeton() = 0;
};
#endif /*THREADS_H_*/
